#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include "cJSON.h"
#define N 4096
char buf[N] = {0};
void *pthread_udp()
{
    udpServerInit();
    return NULL;
}
void *pthread_ftp(void *arg)
{

    cJSON *data = (cJSON *)arg;
    ftpServerInit(data);
    return NULL;
}
int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        printf("请输入正确的参数ip port\n");
    }
    FILE *fp = NULL;
    char *json_string = NULL;
    int n, i;
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("socketfd succ: %d\n", sockfd);
    int opt = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    printf("setsocketopt\n");
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = inet_addr(argv[1]);
    saddr.sin_port = htons(atoi(argv[2]));
    int len = sizeof(caddr);
    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind succ\n");
    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listening client....\n");
    int acceptfd;
    pthread_t tid;
    pthread_create(&tid, NULL, pthread_udp, NULL);
    printf("等待连接Tcp\n");
    while (1)
    {
        acceptfd = accept(sockfd, NULL, NULL);
        printf("tcp 链接成功\n");
        while (1)
        {

            if (acceptfd < 0)
            {
                perror("accept err");
                return -1;
            }
            bzero(buf, N);
            n = recv(acceptfd, buf, N - 1, 0);
            if (n > 0)
            {
                cJSON *root = cJSON_Parse(buf);
                if (!root)
                {
                    printf("Error before: [%s]\n", cJSON_GetErrorPtr());
                    close(acceptfd); // 关闭套接字并继续等待下一个连接
                    continue;
                }
                printf("接收到了消息: %s\n", buf);
                cJSON *type = cJSON_GetObjectItem(root, "type");
                if (!type)
                {
                    printf("Invalid type field in JSON\n");
                    cJSON_Delete(root); // 释放cJSON对象内存
                    close(acceptfd);    // 关闭套接字并继续等待下一个连接
                    continue;
                }
                // 根据type的类型做不同的操作
                switch (type->valueint)
                {
                case 1: // 客户端刚运行会发送这个类型的type，看看需不需要点表
                {
                    cJSON *sroot = cJSON_CreateObject();
                    cJSON_AddNumberToObject(sroot, "type", 1);
                    cJSON_AddNumberToObject(sroot, "result", 0);
                    if (access("/mnt/node.json", F_OK) != -1) // 如果存在点表，需要读取配置信息，传给客户端
                    {
                        //1.读点表
                        char f_buf[2048] = "";
                        fp = fopen("/mnt/node.json", "r");
                        if (fp == NULL)
                        {
                            perror("fopen node err");
                            return -1;
                        }
                        fread(f_buf, 1, sizeof(f_buf), fp);
                        cJSON *root = cJSON_Parse(f_buf);
                        cJSON *report = cJSON_GetObjectItem(root, "report");
                        cJSON *mqtt_server = cJSON_GetObjectItem(root, "mqtt_server");
                        cJSON *mb_dev = cJSON_GetObjectItem(root, "mb_dev");
                        cJSON_AddBoolToObject(sroot, "up_config", 0);
                        cJSON *data = cJSON_CreateObject();
                        cJSON *mqtt_config = cJSON_CreateObject();
                        cJSON_AddStringToObject(mqtt_config, "mqtt_addr", cJSON_GetObjectItem(mqtt_server, "addr")->valuestring);
                        cJSON_AddNumberToObject(mqtt_config, "mqtt_port", cJSON_GetObjectItem(mqtt_server, "port")->valueint);
                        cJSON_AddItemToObject(data, "mqtt_config", mqtt_config);
                        cJSON *video_config = cJSON_CreateObject();
                        cJSON_AddStringToObject(video_config, "video_addr", get_local_ip());
                        cJSON_AddNumberToObject(video_config, "video_port", 8081);
                        cJSON_AddItemToObject(data, "video_config", video_config);
                        cJSON *update_config = cJSON_CreateObject();
                        cJSON_AddNumberToObject(update_config, "type", cJSON_GetObjectItem(report, "type")->valueint);
                        cJSON_AddNumberToObject(update_config, "period", cJSON_GetObjectItem(report, "period")->valueint);
                        cJSON_AddItemToObject(data, "update_config", update_config);
                        cJSON_AddItemToObject(sroot, "data", data);
                    }
                    else // 不存在需要客户端发送点表，给客户端发送的up_config 为true是需要点表
                    {
                        cJSON_AddBoolToObject(sroot, "up_config", 1);
                        json_string = cJSON_Print(sroot);
                    }
                    json_string = cJSON_Print(sroot);
                    printf("send msg: %s\n", json_string);
                    if (send(acceptfd, json_string, strlen(json_string), 0) < 0)
                    {
                        perror("send err");
                    }
                    break;
                }
                case 2: // 类型为2是点表下发，服务器需要点表，然后开启一个ftp服务器接收点表文件并保存。
                {
                    cJSON *data = cJSON_GetObjectItem(root, "data");
                    char *flag = cJSON_GetObjectItem(data, "flag")->valuestring;
                    if (strcmp(flag, "start") == 0)
                    {
                        cJSON *data_copy = cJSON_Duplicate(data, 1);
                        pthread_create(&tid, NULL, pthread_ftp, (void *)data_copy);
                        // 创建并发送JSON响应
                        cJSON *response = cJSON_CreateObject();
                        cJSON_AddNumberToObject(response, "type", 2);
                        cJSON *response_data = cJSON_CreateObject();
                        cJSON_AddStringToObject(response_data, "flag", "start"); // 假设这是响应消息
                        cJSON_AddItemToObject(response, "port", cJSON_CreateNumber(8001));
                        cJSON_AddItemToObject(response, "data", response_data);
                        char *response_string = cJSON_Print(response);
                        if (send(acceptfd, response_string, strlen(response_string), 0) < 0)
                        {
                            perror("send err");
                        }
                        // 释放内存
                        free(response_string);
                    }
                    else if (strcmp(flag, "stop") == 0)
                    {
                        pthread_detach(tid);
                        cJSON *backRoot = cJSON_CreateObject();
                        cJSON_AddItemToObject(backRoot, "type", cJSON_CreateNumber(2));
                        cJSON *bdata = cJSON_CreateObject();
                        cJSON_AddItemToObject(bdata, "flag", cJSON_CreateString("stop"));
                        cJSON_AddItemToObject(backRoot, "data", bdata);
                        char *backJson = cJSON_Print(backRoot);
                        if (send(acceptfd, backJson, strlen(backJson), 0) < 0)
                        {
                            perror("backjson send err");
                        }
                    }

                    break;
                }
                case 3: // 心跳检测机制
                {
                    cJSON *alive = cJSON_CreateObject();
                    cJSON_AddItemToObject(alive, "type", cJSON_CreateNumber(3));
                    cJSON_AddItemToObject(alive, "result", cJSON_CreateNumber(0));
                    char *sendBuf = cJSON_Print(alive);
                    if (send(acceptfd, sendBuf, strlen(sendBuf), 0) < 0)
                    {
                        perror("alive send err");
                    }
                    break;
                }

                default:
                    break;
                }
                // 释放cJSON对象占用的内存
                cJSON_Delete(root);
            }
            else if (n == 0)
            {
                close(acceptfd);
            }
            else
            {
                perror("220 tcp recv err");
                close(acceptfd);
                break;
            }
        }
    }
    pthread_detach(tid);
    return 0;
}
